package com.leador.map.api.location;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;

import com.leador.map.api.location.core.LocationException;
import com.leador.map.api.location.core.ClientInfoUtil;
import com.leador.map.api.location.core.CoreUtil;

import com.leador.map.location.ILocationService;
import com.leador.map.location.LocationInfo;
import com.leador.map.location.LocationServiceFactory;
import com.leador.map.location.util.AuthManager;
import com.leador.map.location.util.ConfigableConst;
import com.leador.map.location.util.NetUtil;
import com.leador.map.location.util.SDKInfo;
import com.leador.map.location.util.Utils;

/**
 * 网络定位管理器
 */
public class NetworkLocationManager implements Runnable {
    private static NetworkLocationManager _instance;
    //
	private ILocationService locationService = null;
    //
	private volatile static boolean threadFlag = true;
	private Thread runThread = null;
	private Context context;

	private long sleepTime = 2 * 1000;
	private long mPriorityWaitingTime = 60 * 1000;
	private int mPriority;
	private MapLocationManager.MapLocationHandler mapLocationHandler;
    private ConnectivityManager cm;
    /**
     * 保护构造函数
     * @param context
     * @param mapLocationHandler
     */
	protected NetworkLocationManager(Context context,
                                     MapLocationManager.MapLocationHandler mapLocationHandler) {
		this.context = context;
		locationService = LocationServiceFactory.getInstance();
		ClientInfoUtil.getInstance(context);
		// 设置进行定位所必须的产品名
		locationService.init(context);
		locationService.setAuth("leador_locsdk##" + CoreUtil.LICENSE + "##"
                + ClientInfoUtil.getKey(context) + ","
                + ClientInfoUtil.getPackageName());
		//
		this.mapLocationHandler = mapLocationHandler;
		cm = (ConnectivityManager) Utils.getService(context, Context.CONNECTIVITY_SERVICE);

	}

    /**
     * 获取单实例
     * @param context
     * @param mapLocationHandler
     * @return
     */
	public static NetworkLocationManager getInstance(Context context,
			MapLocationManager.MapLocationHandler mapLocationHandler) {
        synchronized (NetworkLocationManager.class) {
            if (_instance == null) {
                _instance = new NetworkLocationManager(context, mapLocationHandler);
            }
        }
		threadFlag = true;
		return _instance;
	}

	public void destroy() {
		threadFlag = false;
		if (runThread != null) {
			runThread.interrupt();
		}
        locationService.destroy();
		locationService = null;
		_instance = null;
	}

	@Override
	public void run() {
		if (mPriority == 1) {
			try {
				Thread.sleep(mPriorityWaitingTime);
			} catch (Exception e) {
				Thread.currentThread().interrupt();
			}
		}
		while (threadFlag) {
			runThread = Thread.currentThread();
			LocationInfo locationInfo = null;
			MapLocation aloc = null;
			try {
				if ((MapLocationManager.mGpsFixed && (!isOverTime()))
						|| (!MapLocationManager.locEnable)) {
					try {
						Thread.sleep(sleepTime);
					} catch (Exception e) {
						Thread.currentThread().interrupt();
					}
					continue;
				}
                //获取网络定位结果
                if(!checkNet()){
					throw new LocationException(LocationException.ERROR_IO);
				}
				locationInfo = authNetworkLocation();
				if (locationInfo != null) {
					aloc = transformLocation(locationInfo);
				}
			} catch (LocationException e) {
				sendFailManager(e.getErrorMessage());
			} catch (Exception e) {

			} finally {
				if (aloc != null && MapLocationManager.locEnable) {
					if (!MapLocationManager.mGpsFixed || isOverTime()) {
						sendSuccessManager(aloc);
					}
				}
				try {
					Thread.sleep(sleepTime);
				} catch (Exception e) {
					Thread.currentThread().interrupt();
				}
			}
		}
	}
	private boolean checkNet(){
		if(cm==null){
			return false;
		}
		NetworkInfo ni = cm.getActiveNetworkInfo();
		int iNetworkType = NetUtil.getNetworkType(ni);
		if (iNetworkType == -1) {
			return false;
		}
		return true;
	}
    private void sendSuccessManager(MapLocation aloc){
		if(mapLocationHandler==null){
			return ;
		}
		Message msg = new Message();
		msg.obj = aloc;
		msg.what = MapLocationManager.LOCATION_MESSAGE_SUCCESS;
		mapLocationHandler.sendMessage(msg);
	}
	private void sendFailManager(String errDesc){
		if(mapLocationHandler==null){
			return ;
		}
		Message msg = new Message();
		MapLocation aloc = new MapLocation("");
		aloc.setErrorInfo(errDesc);
		msg.obj = aloc;
		msg.what = MapLocationManager.LOCATION_MESSAGE_FAIL;
		mapLocationHandler.sendMessage(msg);
	}
    /**
     * 定位间隔设置
     * @param milliseconds
     */
	public void setRequestTime(long milliseconds) {
		if (milliseconds > sleepTime) {
			sleepTime = milliseconds;
		}
	}

    /**
     * 认证网络定位，如果认证成功则执行定位
     * @return
     * @throws Exception
     */
	private LocationInfo authNetworkLocation() throws LocationException {
		LocationInfo locationInfo = null;
		switch (AuthManager.authResult){
			case -1://第一次鉴权
				startAuthThread();
				locationInfo = getNetworkLocation();
				break;
			case AuthManager.AUTH_SUCCESS://鉴权成功
				locationInfo = getNetworkLocation();
				break;
			default://鉴权失败
                throw new LocationException(LocationException.ERROR_FAILURE_AUTH);
		}
//		if (AuthManager.authResult == -1) {
//			SDKInfo sdkInfo = new SDKInfo.init(ConfigableConst.product,"1.0.0", ConfigableConst.desc);
//			boolean success = AuthManager.getKeyAuth(context,sdkInfo);
//			if (success) {
//				locationInfo = getNetworkLocation();
//			}
//		} else {
//			if (AuthManager.AuthState == AuthManager.AUTH_SUCCESS) {
//				locationInfo = getNetworkLocation();
//			}
//		}
		return locationInfo;
	}
    private boolean isAuthing = false;
    private void startAuthThread(){
		if(isAuthing){
			return ;
		}
		synchronized (this) {
			isAuthing = true;
			new Thread() {
				public void run() {
					try {
						Log.e("networkmanager","startAuthThread");
						SDKInfo sdkInfo = new SDKInfo.init(ConfigableConst.product, "1.0.0", ConfigableConst.desc).getSDKInfo();
						boolean success = AuthManager.getKeyAuth(context, sdkInfo);
						Log.e("networkmanager","auth end :"+success +" res:"+AuthManager.authResult);
					} catch (Exception ex) {
						ex.printStackTrace();
					}finally {

						isAuthing = false;
					}
				}
			}.start();
		}
	}
    /**
     * 设置是否使用Gps
     * @param useGps
     */
    public void setUseGps(boolean useGps){
        locationService.setUseGps(useGps);
    }
    /**
     * 获取网络定位结果
     * @return
     */
	private LocationInfo getNetworkLocation() {
        //
		LocationInfo locationInfo = null;
		try {
			if(locationService!=null){
				locationInfo = locationService.getLocation();
			}
		} catch (Exception e) {
			//
			e.printStackTrace();
		}
		verifyOverAuthSpan();
		return locationInfo;
	}

    /**
     * 确认是否超过免认证间隔
     */
	private void verifyOverAuthSpan() {
//		AuthManager.LocaitonCount++;
//		if (AuthManager.LocaitonCount == 1000) {
//			AuthManager.AuthState = AuthManager.NOT_AUTH;
//			AuthManager.LocaitonCount = 0;
//		}
	}

    /**
     * 是否Gps定位结果超时了
     * @return
     */
	private boolean isOverTime() {
		long currTime = System.currentTimeMillis();
		if (currTime - MapLocationManager.mLastGpsFixedTime > (5 * sleepTime)) {
			MapLocationManager.mGpsFixed = false;
			return true;
		} else {
			return false;
		}
	}

    /**
     *
     * @param locationInfo
     * @return
     */
	private MapLocation transformLocation(LocationInfo locationInfo) {
		MapLocation androidLocation = new MapLocation("lbs");
        //
		androidLocation.setProvider(LocationProviderProxy.LocNetwork);
		androidLocation.setLatitude(locationInfo.getLat());
		androidLocation.setLongitude(locationInfo.getLon());
		androidLocation.setAccuracy(locationInfo.getAccuracy());
		androidLocation.setTime(locationInfo.getTime());
		androidLocation.setCityCode(locationInfo.getCitycode());
        androidLocation.setAdCode(locationInfo.getAdcode());
		androidLocation.setAddress(locationInfo.getDesc());
//		Bundle bundle = new Bundle();
//		bundle.putString("citycode", locationInfo.getCitycode());
//		bundle.putString("desc", locationInfo.getDesc());
//		bundle.putString("adcode", locationInfo.getAdcode());
//		androidLocation.setExtras(bundle);
		String cityCode = locationInfo.getCitycode();
		String desc = locationInfo.getDesc();
		String adcode = locationInfo.getAdcode();
		try {
			analysisLocDesc(androidLocation, cityCode, adcode, desc);
		} catch (Exception e) {

		}
		return androidLocation;
	}

	private void analysisLocDesc(MapLocation androidLocation, String cityCode,
			String adcode, String desc) {
		String[] descs = desc.split(" ");
		androidLocation.setCityCode(cityCode);
		androidLocation.setAdCode(adcode);
		if ((!cityCode.equals("")) && isDirectlyCity(cityCode)) {
			if (descs.length > 2) {
				androidLocation.setCity(descs[0]);
				androidLocation.setDistrict(descs[1]);
			}

		} else {
			if (descs.length > 3) {
				androidLocation.setProvince(descs[0]);
				androidLocation.setCity(descs[1]);
				androidLocation.setDistrict(descs[2]);
			}
		}
	}

	private boolean isDirectlyCity(String cityCode) {
		if (cityCode.endsWith("010") || cityCode.endsWith("021")
				|| cityCode.endsWith("022") || cityCode.endsWith("023")) {
			return true;
		} else {
			return false;
		}
	}

}